/** 
 * @file Animation.h 
 * 
 * @brief  Declares the Animation and animation caching.
 * @author Bas du Pre
 * @date   26-05-2011
 * 
 **/ 

#pragma once

#include "../global.h"

#include "TextureFrame.h"
#include "../Events.h"
#include "../Map.h"

namespace Prism {
namespace Graphics {
    
    class Animation;
    
    ///\cond INTERNAL
    class _PRISM_AnimationCache {
        
        _PRISM_AnimationCache();
        virtual ~_PRISM_AnimationCache();
        
        static _PRISM_AnimationCache *s_instance;
        
    public:
        static _PRISM_AnimationCache *instance();
        Map<String, Animation*> animations;
    };
    ///\endcond
    
    /**
     * \brief Class that defines a frame animation.
     * 
     * An Animation object is used to define frame animations. Frame animations
     * can be performed by Sprite objects.
     *
     * Animation objects contain a sequence of TextureFrames and a delay between
     * the frames.
     *
     * \todo property to set loop mode (single shot, loop, back and forth)
     */
     
    class Animation : public PObject {
    public:
        Animation();
        virtual ~Animation();
        
        /// Adds a texture frame to the end of this animation.
        void addFrame(TextureFrame *frame);
        /// \brief Inserts a texture frame at an index in this animation.
        /// \param frame Pointer to the texture frame.
        /// \param i     Index to insert the frame at
        void addFrame(TextureFrame *frame, int i);
        
        /// Removes the first occurrence of a TextureFrame in this animation.
        void removeFrame(TextureFrame *f);
        /// Removes the frame at a certain index from this animation.
        void removeFrame(int i);
        
        /// Returns a pointer to the frame at a certain index in this animation.
        TextureFrame *getFrame(int i);
        
        /// \brief Returns the length in frames of this animation.
        /// \return the number of frames in this animation.
        int length();
        
        ///\name Properties
        ///\{
        
        /// \brief Set whether this Animation should automatically delete a TextureFrame when it
        /// is not needed anymore.
        ///
        /// \sa autodelete();
        void setAutodelete(bool autodelete);
        
        /// \brief Returns whether this Animation should automatically delete a TextureFrame when it
        /// is not needed anymore.
        ///
        /// This can be because it is manually removed from the sequence or because the
        /// Animation object is destroyed.
        bool autodelete();
        
        /// \brief Sets the delay between each frame in seconds.
        void setDelay(PFloat delay);
        /// \brief Returns the delay between each frame in seconds.
        PFloat delay();
        ///\}
        
        /// Returns a String representing this Animation.
        virtual String toString();
        
        /// \brief Save this Animation to the global animation cache.
        ///
        /// \param name The name representing this Animation.
        void save(String name);
        
        /// \brief Retrieves an Animation from the global animation cache.
        ///
        /// \param name A name representing an Animation.
        /// \return The Animation represented by the name or 0 if it does not exist.
        static Animation* withName(String name);
        
        /// \brief Removes an Animation from the global animation cache.
        static void forget(Animation * animation);
        /// \brief Removes the Animation represented by a name from the global animation cache.
        /// \param name A name representing an Animation.
        static void forget(String name);
        
    private:
        List<TextureFrame*> frames;
        bool _autodelete;
        PFloat _delay;
        
    public:
        //#if PRISM_OS_IOS
        //#include "iOS/ios_Texture.h"
        //#endif
        
    };
    
    
}
}